package com.photoeditor.demo.ad;

import android.content.Context;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.text.TextUtils;

import com.billing.base.svip.SVipManager;
import com.common.base.ComponentContext;
import com.common.base.log.DLog;
import com.common.base.utils.DebugUtil;
import com.common.base.utils.thread.ThreadPool;
import com.common.commercialize.ad.AdDisplay;
import com.common.commercialize.ad.AdManager;
import com.common.commercialize.ad.third.IAd;
import com.common.commercialize.ad.third.ThirdAdListener;
import com.common.commercialize.sdk.CommercializeSDK;
import com.common.commercialize.utils.SceneStatisticsNew;
import com.photoeditor.R;
import com.photoeditor.demo.model.subscribe.manager.AppVipManager;
import com.photoeditor.demo.statistics.StatisticsConstant;
import com.photoeditor.demo.statistics.StatisticsUtils;
import com.wv.nw.activity.AdActivity;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;


/**
 * Created by mutour on 2017/7/19.
 */

public class AdProvider {
    private final String TAG = AdProvider.class.getName();
    private String mSceneName;
    private String mStatisticsName;
    private String mUnitAd;
    private String mSuffix = "";
    private int mFunId;
    private int mRequestTimes = 0;

    public static final String REASON_SVIP_USER = "svip_user";
    public static final String REASON_SHOULD_SHOW_SVIP = "should_show_svip";
    public static final String REASON_BUY_USER = "buy_user";
    public static final String REASON_NO_BUY_USER = "no_buy_user";
    public static final String REASON_UNIT_ID_ERROR = "unit_id_error";
    public static final String REASON_PROTOCOL_UN_FIT = "protocol_un_fit";
    public static final String REASON_TRIGGER_TYPE_EMPTY = "trigger_type_empty";
    public static final String REASON_TRIGGER_TYPE_MISMATCH = "trigger_type_mismatch";
    public static final String REASON_LOCAL_SHOW_COUNT_LIMIT = "local_show_count_limit";
    public static final String REASON_LOCAL_SHOW_TIME_INTERVAL_LIMIT = "local_show_time_interval_limit";
    public static final String REASON_NO_VALID_AD = "no_valid_ad";
    public static final String REASON_AD_OBJECT_ERROR = "ad_object_error";
    public static final String REASON_PAGE_NO_SHOWING = "page_no_showing";
    public static final String REASON_AD_SHOWING = "ad_showing";
    public static final String REASON_CODE_ERROR = "code_error";
    public static final String REASON_NETWORK_ERROR = "network_error";
    public static final String REASON_NO_FLOW_DATA = "no_flow_data";
    public static final String REASON_FLOW_AD_LIMIT = "flow_ad_limit";
    public static final String REASON_PLUGIN_VERSION_TOO_LOW = "plugin_version_too_low";

    @IntDef({
            AdType.All,
            AdType.Native,
            AdType.Interstitial
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AdType {
        int All = 0;
        int Native = 1;
        int Interstitial = 2;
    }

    private int mAdType = AdType.Native;

    private List<String> mAdCacheNames = new CopyOnWriteArrayList<>();

    private OnAdListener mOnAdListener;
    private List<String> mStatisticsInfoList = new ArrayList<>();
    final Object lock = new Object();

    public AdProvider(@NonNull String sceneName, @NonNull String unitId, int funId) {
        this(sceneName, unitId, funId, sceneName);
    }

    public AdProvider(@NonNull String sceneName, @NonNull String unitId, int funId, String statisticsName) {
        mSceneName = sceneName;
        mStatisticsName = statisticsName;
        mUnitAd = unitId;
        mFunId = funId;
    }

    public static AdProvider newProvider(@NonNull String sceneName, @NonNull String unitId, int funId) {
        return new AdProvider(sceneName, unitId, funId);
    }

    public static AdProvider newProvider(@NonNull String sceneName, @NonNull String unitId, int funId, String statisticsName) {
        return new AdProvider(sceneName, unitId, funId, statisticsName);
    }

    public void setStatisticsInfo(String... info) {
        mStatisticsInfoList.clear();
        mStatisticsInfoList.addAll(Arrays.asList(info));
    }

    public void addStatisticsInfo(String... info) {
        mStatisticsInfoList.addAll(Arrays.asList(info));
    }

    public void setUnitAd(@NonNull String unitId) {
        mUnitAd = unitId;
    }

    public void setFunId(int funId) {
        mFunId = funId;
    }

    public void setSuffix(String suffix) {
        if (suffix == null) {
            suffix = "";
        }
        mSuffix = suffix;
    }

    public void setAdType(@AdType int adType) {
        this.mAdType = adType;
    }

    public void setOnAdListener(OnAdListener listener) {
        mOnAdListener = listener;
    }

    public OnAdListener getOnAdListener() {
        return mOnAdListener;
    }

    public void loadAd(final AdManager.AdRequest adRequest) {
        if (AppVipManager.isVip()) {
            statisticsNoRequestAd(REASON_SVIP_USER);
            return;
        }

        adRequest.setSuffix(mSuffix)
                .setFunId(mFunId)
                .setBatmobiUnitId(mUnitAd);

        ProviderAdListener providerAdListener = new ProviderAdListener();
        providerAdListener.setAdCacheKey(adRequest.makeCacheKey());//key的建立规则一致，可以先建Key
        adRequest.setAdListener(providerAdListener);

        AdManager.getInstance().loadAd(ComponentContext.getContext(), adRequest);
    }

    public void statisticsNoRequestAd(String reason) {
//        List<String> statisticsInfo = new ArrayList<>(mStatisticsInfoList);
//        statisticsInfo.addAll(Arrays.asList(
//                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_UID, mUnitAd,
//                "reason", reason == null ? "un_know" : reason,
//                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_STATE, String.valueOf(false)));
//        SceneStatisticsNew.statistics(mStatisticsName + SceneStatisticsNew.EVENT_SUFFIX_AD_REQUEST,
//                statisticsInfo.toArray(new String[statisticsInfo.size()]));
    }

    public static void statisticsNoRequestAd(String statisticsName, String reason) {
//        List<String> statisticsInfo = new ArrayList<>();
//        statisticsInfo.addAll(Arrays.asList(
//                "reason", reason == null ? "un_know" : reason,
//                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_STATE, String.valueOf(false)));
//        SceneStatisticsNew.statistics(statisticsName + SceneStatisticsNew.EVENT_SUFFIX_AD_REQUEST,
//                statisticsInfo.toArray(new String[statisticsInfo.size()]));
    }

    public void statisticsNoShowAd(String reason) {
//        List<String> statisticsInfo = new ArrayList<>(mStatisticsInfoList);
//        statisticsInfo.addAll(Arrays.asList(
//                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_UID, mUnitAd,
//                "reason", reason == null ? "un_know" : reason,
//                "hasAd", String.valueOf(hasAd()),
//                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_STATE, String.valueOf(false)));
//        SceneStatisticsNew.statistics(mStatisticsName + SceneStatisticsNew.EVENT_SUFFIX_AD_SHOW,
//                statisticsInfo.toArray(new String[statisticsInfo.size()]));
    }

    public static void statisticsNoShowAd(String statisticsName, String reason) {
//        List<String> statisticsInfo = new ArrayList<>();
//        statisticsInfo.addAll(Arrays.asList(
//                "reason", reason == null ? "un_know" : reason,
//                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_STATE, String.valueOf(false)));
//        SceneStatisticsNew.statistics(statisticsName + SceneStatisticsNew.EVENT_SUFFIX_AD_SHOW,
//                statisticsInfo.toArray(new String[statisticsInfo.size()]));
    }

    public void loadAd() {
        Context context = ComponentContext.getContext();
        final AdManager.AdRequest adRequest = new AdManager.AdRequest();
        adRequest.setSceneName(mSceneName)
                .addAllNativeByDefault(context);
        loadAd(adRequest);

        List<String> statisticsInfo = new ArrayList<>(mStatisticsInfoList);
        statisticsInfo.addAll(Arrays.asList(
                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_UID, mUnitAd,
                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_TYPE, "null",
                StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_SCENE, mSceneName));
//        SceneStatisticsNew.statistics(mStatisticsName + SceneStatisticsNew.EVENT_SUFFIX_AD_REQUEST,
//                statisticsInfo.toArray(new String[statisticsInfo.size()]));
        StatisticsUtils.statisticGrowingIo(StatisticsConstant.UMENG_CUSTOM_ENENT_REQUEST,
                statisticsInfo.toArray(new String[statisticsInfo.size()])
                );
    }

    public String getAdCacheKey() {
        synchronized (lock) {
            if (mAdCacheNames.size() > 0) {
                return mAdCacheNames.remove(0);
            }
        }
        return "";
    }

    public int size() {
        synchronized (lock) {
            return mAdCacheNames.size();
        }
    }

    public boolean hasAd() {
        synchronized (lock) {
            return !mAdCacheNames.isEmpty();
        }
    }

    public ProviderAdListener getAdListener() {
        return new ProviderAdListener();
    }

    public void destroy() {
        synchronized (lock) {
            for (String key : mAdCacheNames) {
                AdManager.getInstance().destoryAd(key);
            }
            mOnAdListener = null;
            mAdCacheNames.clear();
        }
    }

    public abstract static class OnAdListener {
        public void onAdLoadFinish(String cacheKey) {
        }

        public void onAdLoadFailure(String err) {
        }

        public void onAdClicked(String cacheKey) {
        }

        public void onAdImpression(String cacheKey) {
        }

        public void onAdClosed(String cacheKey) {
        }
    }

    public void showNextAd(Context context) {
        if (AppVipManager.isVip()) {
            return;
        }

        String adCacheKey = getAdCacheKey();
        if (!AdManager.getInstance().hasAd(adCacheKey)) {
            return;
        }
        Object ad = AdManager.getInstance().getAd(adCacheKey);
        if(ad == null) {
            return;
        }
        new AdDisplay.Builder(context, AdActivity.class)
                .setKey(adCacheKey)
                .setLayoutId(R.layout.commercialize_ad_style_2)
                .setDefaultResId(R.drawable.ic_default_image)
                .show(ad);
    }

    /**
     * 广告监听，每个AdProvider独立
     * <p>
     * 需提前调用{@ProviderAdListener.setAdCacheKey}设置广告Key
     */
    public class ProviderAdListener extends ThirdAdListener {

        String adCacheKey;

        public void setAdCacheKey(String adCacheKey) {
            this.adCacheKey = adCacheKey;
        }

        @Override
        public void onAdRequest(IAd var1) {
//            List<String> statisticsInfo = new ArrayList<>(mStatisticsInfoList);
//            statisticsInfo.addAll(Arrays.asList(
//                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_UID, mUnitAd,
//                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_STATE, String.valueOf(true),
//                    SceneStatisticsNew.UMENG_CUSTOM_EVENT_KEY_ADSOURCE, null));
//            SceneStatisticsNew.statistics(mStatisticsName + SceneStatisticsNew.EVENT_SUFFIX_AD_REQUEST,
//                    statisticsInfo.toArray(new String[statisticsInfo.size()]));
        }

        @Override
        public void onAdClose(IAd var1) {
            final String key = adCacheKey;
            if (mOnAdListener != null) {
                ThreadPool.runUITask(new Runnable() {
                    @Override
                    public void run() {
                        if (mOnAdListener != null) {
                            mOnAdListener.onAdClosed(key);
                        }
                    }
                });

            }
        }

        @Override
        public void onError(IAd ad, String err) {
            if (CommercializeSDK.TestUser.isTestUser() || DebugUtil.isDebuggable()) {
                if (!TextUtils.isEmpty(mUnitAd)) {
                    TestAd testAd = new TestAd(adCacheKey);
                    testAd.loadInternal();
                    testAd.setAdListener(this);
                    AdManager.getInstance().putAd(adCacheKey, testAd);
                    onAdLoaded(testAd);
                    return;
                }
            } else {
                if (mOnAdListener != null) {
                    mOnAdListener.onAdLoadFailure(err);
                }
            }

            if (DebugUtil.isDebuggable()) {
                DLog.d(TAG, mSceneName + " onError:" + err);
            }
            SceneStatisticsNew.statistics(SceneStatisticsNew.EVENT_SCENE_TRIGGER_FAIL, mStatisticsName, err);
        }

        @Override
        public void onAdLoaded(final IAd ad) {
            final String key = adCacheKey;
            if (DebugUtil.isDebuggable()) {
                DLog.d(TAG, mSceneName + " onAdLoaded:" + key);
            }

            synchronized (lock) {
                mAdCacheNames.add(key);
            }
            if (mOnAdListener != null) {
                ThreadPool.runUITask(new Runnable() {
                    @Override
                    public void run() {
                        if (mOnAdListener != null) {
                            mOnAdListener.onAdLoadFinish(key);
                        }
                    }
                });

            }

            List<String> statisticsInfo = new ArrayList<>(mStatisticsInfoList);
            statisticsInfo.addAll(Arrays.asList(
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_UID, mUnitAd,
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_TYPE, "null",
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_SCENE, mSceneName));
            StatisticsUtils.statisticGrowingIo(StatisticsConstant.UMENG_CUSTOM_ENENT_LOAD,
                    statisticsInfo.toArray(new String[statisticsInfo.size()]));
        }

        @Override
        public void onAdClicked(IAd ad) {
            final String key = adCacheKey;

            if (DebugUtil.isDebuggable()) {
                DLog.d(TAG, mSceneName + " onAdClicked");
            }
            if (mOnAdListener != null) {
                ThreadPool.runUITask(new Runnable() {
                    @Override
                    public void run() {
                        if (mOnAdListener != null) {
                            mOnAdListener.onAdClicked(key);
                        }
                    }
                });

            }

            List<String> statisticsInfo = new ArrayList<>(mStatisticsInfoList);
            statisticsInfo.addAll(Arrays.asList(
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_UID, mUnitAd,
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_TYPE, "null",
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_SCENE, mSceneName));
            StatisticsUtils.statisticGrowingIo(StatisticsConstant.UMENG_CUSTOM_ENENT_CLICK,
                    statisticsInfo.toArray(new String[statisticsInfo.size()]));
        }

        @Override
        public void onLoggingImpression(IAd ad) {
            if (DebugUtil.isDebuggable()) {
                DLog.d(TAG, mSceneName + " onLoggingImpression");
            }
            final String key = adCacheKey;
            if (mOnAdListener != null) {
                ThreadPool.runUITask(new Runnable() {
                    @Override
                    public void run() {
                        if (mOnAdListener != null) {
                            mOnAdListener.onAdImpression(key);
                        }
                    }
                });
            }

            List<String> statisticsInfo = new ArrayList<>(mStatisticsInfoList);
            statisticsInfo.addAll(Arrays.asList(
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_UID, mUnitAd,
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_TYPE, "null",
                    StatisticsConstant.UMENG_CUSTOM_EVENT_KEY_AD_SCENE, mSceneName));
            StatisticsUtils.statisticGrowingIo(StatisticsConstant.UMENG_CUSTOM_ENENT_SHOW,
                    statisticsInfo.toArray(new String[statisticsInfo.size()]));
        }
    }
}
